package controller

import (
	"BlazeRider-backend/app/manager"
	"BlazeRider-backend/app/models"
	"BlazeRider-backend/app/service"
	"BlazeRider-backend/app/utils"
	"BlazeRider-backend/routes"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/gorilla/websocket"
	"math/rand"
	"net/http"
	"reflect"
	"strconv"
	"sync"
	"time"
)

// Message 结构体用于封装WebSocket消息
type Message struct {
	Event     string        `json:"event"`
	AuthToken string        `json:"auth"`
	MessageId string        `json:"message_id"`
	Data      InMessageData `json:"data"`
}

// Message的 Data 结构体用于封装WebSocket消息
type InMessageData struct {
	GiftNum   int    `json:"gift_num"`
	GiftValue int    `json:"gift_value"`
	GiftId    string `json:"gift_id"`
	Name      string `json:"name"`
	Content   string `json:"content"`
	RoomId    string `json:"room_id"`
	Token     string `json:"token"`
}

type IndexController struct {
	mu sync.Mutex // 添加互斥锁字段
}

//func NewIndexController(m *manager.Managers) *IndexController {
//	// 启动每分钟检查分数的定时任务
//	//scoreManager.StartRoundScoreTicker()
//	return &IndexController{
//		connManager:       m.ConnectionManager(),
//		scoreManager:      m.ScoreManager(),
//		eventManager:      m.EventManager(),
//		giftManager:       m.GiftManager(),
//		userManager:       m.UserManager(),
//		liveRoomManager:   m.LiveRoomManager(),
//		giftRecordManager: m.ClientErrorRecordManager(),
//	}
//}

func NewIndexController() *IndexController {
	// 启动每分钟检查分数的定时任务
	//scoreManager.StartRoundScoreTicker()
	return &IndexController{}
}

// controller/indexController.go
func (i *IndexController) RegisterRoutes(router *gin.Engine) {
	// 注册原有路由
	groupIndex := router.Group("/index")
	{
		groupIndex.GET("/regist", i.Regist)
		groupIndex.GET("/index", i.Index)
		groupIndex.GET("/game/index", i.GameIndex)
	}

	groupWsAnchor := router.Group("/ws/anchor")
	{
		groupWsAnchor.GET("/game/start", i.GameStart)
		groupWsAnchor.GET("/rank", i.Rank)
	}

	// 其他原有路由...
}

func (i *IndexController) Index(ctx *gin.Context) {
	ctx.HTML(http.StatusOK, "index.html", map[string]interface{}{
		"title": "首页",
	})
}

func (i *IndexController) GameIndex(ctx *gin.Context) {
	ctx.HTML(http.StatusOK, "game.html", map[string]interface{}{
		"title": "游戏",
	})
}

func (i *IndexController) Regist(ctx *gin.Context) {
	conn, err := upGrader.Upgrade(ctx.Writer, ctx.Request, nil)
	if err != nil {
		fmt.Println("websocket error:", err)
		return
	}

	liveRoomToken := ctx.Query("liveRoomToken")

	if liveRoomToken == "" {
		fmt.Println("直播间token为空")
		conn.Close()
		return
	}

	liveRoomUserInfo, loginToken, err := service.AuthService{}.SetAuth(liveRoomToken)
	if err != nil {
		fmt.Println("直播间token获取抖音信息出错, error: %v", err)
		return
	}

	manager.Get().ConnectionManager().Register(conn, liveRoomUserInfo.RoomId, liveRoomUserInfo.AnchorOpenId)

	// TODO
	liveRoomInfo, err := manager.Get().LiveRoomManager().GetLiveInfo(liveRoomUserInfo.RoomId)
	if err == nil {
		if liveRoomInfo.State == "start" {
			service.DouYinService{}.StartDouYinLiveRoomAllTask(liveRoomUserInfo.RoomId)
		}
	} else {
		fmt.Println("get live room err : ", err)
	}

	headImgArr := []string{
		"http://82.157.179.66:8001/static/03763e7c5fd77d3ba9d0ed2b35f5bfeb.jpeg",
		"http://82.157.179.66:8001/static/16e1041e5e02db1c77678084102a9b6b.jpeg",
		"http://82.157.179.66:8001/static/8944face68cc71bc452ea8a4fd0abc5b.jpeg",
		"http://82.157.179.66:8001/static/9c19c581f33e134b252d44dbc5ddef67.jpg",
		"http://82.157.179.66:8001/static/1a59df123cac3944d1104dd164160888.jpeg",
		"http://82.157.179.66:8001/static/d5ade3fccf97e1fc59ba2c7c63619cf9.jpg",
		"http://82.157.179.66:8001/static/a45f096821bb09659443c512c204ec47.jpeg",
		"http://82.157.179.66:8001/static/391b8b23c018e957d38b6787f0791fa7.jpeg",
	}

	// 初始化随机数种子
	rand.Seed(time.Now().UnixNano())

	// 生成1到10的随机数
	levelNum := 1

	headIndex := rand.Intn(8)

	//i.userManager.InitializeUser(userId, userName, headImgArr[headIndex], levelNum)
	err = manager.Get().UserManager().InitializeUser(liveRoomUserInfo.AnchorOpenId, liveRoomUserInfo.NickName, headImgArr[headIndex], levelNum)
	if err != nil {
		fmt.Printf("Failed to Initialize User: %v\n", err)
	}

	i.returnGenTokenMsg(conn, loginToken, liveRoomUserInfo.RoomId)

	backDataByTime := ctx.Query("backDataByTime")

	// 获取变量的反射对象
	value := reflect.ValueOf(backDataByTime)
	// 获取变量的类型信息
	typ := value.Type()

	fmt.Println("register backDataByTime backDataByTime : ", backDataByTime, typ)

	if !(backDataByTime == "" || backDataByTime == "0") {
		fmt.Println("register backDataByTime backDataByTime into if : ", backDataByTime)
		backDataByTimeI64, _ := strconv.ParseInt(backDataByTime, 10, 64)

		fmt.Println("service.DealBackDataByTime : ", liveRoomInfo.LiveRoomId, liveRoomInfo.Times, backDataByTimeI64)

		go service.DealBackDataByTime(conn, liveRoomInfo.LiveRoomId, liveRoomInfo.Times, backDataByTimeI64)
	}

	// 得到客户的连接ip和端口
	fmt.Println("client connect:", conn.RemoteAddr())
	go i.Do(conn, liveRoomUserInfo.RoomId)
}

func (i *IndexController) HandleStartGameMessage(conn *websocket.Conn, msg Message) {
	// 从conn获取LiveRoomID和ConnInfo
	connInfo, found := manager.Get().ConnectionManager().GetConnInfo(conn)
	if !found {
		fmt.Println("error: connInfo not found for the given connection")
		return
	}

	liveRoomID := connInfo.ID
	userId := connInfo.UserId

	manager.Get().LiveRoomManager().SetLiveRoomStatus(liveRoomID, true)
	manager.Get().ScoreManager().InitializeRoom(liveRoomID)

	// 获取当前时间
	now := time.Now()

	userName := ""
	userHeadImg := ""
	level := 0
	userScore := 0
	//userInfo, err := i.userManager.GetUser(userId)
	userInfo, err := manager.Get().UserManager().GetUser(userId)
	if err == nil {
		userName = userInfo.UserName
		userHeadImg = userInfo.HeadImg
		level = userInfo.Level
		userScore = userInfo.Score
	}

	if liveRoomID != utils.TestRoomId {
		err := service.DouYinService{}.StartDouYinLiveRoomAllTask(liveRoomID)
		if err != nil {
			fmt.Println("start dou yin live room all task err : ", err, ", room id : ", liveRoomID)
		}

		var finishTrackInfo []models.FinishTrackInfo
		// status 为1是开始
		err = service.DouYinService{}.SyncGameStatusToDouYinService(liveRoomID, 1, finishTrackInfo)
		if err != nil {
			fmt.Println("sync game status start to dou yin err : ", err, ", room id : ", liveRoomID)
		}

	}

	// 创建一个开始游戏的事件
	data := models.LiveEventData{
		Event: "broad_start_game",
		Data: struct {
			MsgID         string `json:"msg_id"`         // 事件的ID
			SecOpenID     string `json:"sec_openid"`     // 用户的加密openid
			Type          string `json:"type"`           // 事件类型：comment, gift, like
			Content       string `json:"content"`        // 评论内容（仅评论有效）
			Camp          int    `json:"camp"`           // 所属阵营
			Job           int    `json:"job"`            // 所属职业
			SecGiftID     string `json:"sec_gift_id"`    // 加密的礼物id（仅礼物有效）
			GiftNum       int    `json:"gift_num"`       // 送出的礼物数量（仅礼物有效）
			GiftValue     int    `json:"gift_value"`     // 礼物总价值，单位分（仅礼物有效）
			Name          string `json:"name"`           // 用户昵称
			Level         int    `json:"level"`          // 用户等级
			AccGiftScore  int    `json:"acc_gift_score"` // 直播间当前用户累计礼物价值
			LikeNum       string `json:"like_num"`       // 点赞数量（仅点赞有效）
			AvatarURL     string `json:"avatar_url"`     // 用户头像
			Nickname      string `json:"nickname"`       // 用户昵称
			UserScore     int    `json:"user_score"`     // 用户积分
			GiftLevel     int    `json:"gift_level"`     // 礼物等级
			GiftUpgrading int    `json:"gift_upgrading"` // 礼物当前次升级
			GameScore     int    `json:"game_score"`     // 游戏当局分数
			Timestamp     int64  `json:"timestamp"`      // 事件时间戳
		}{
			MsgID:     uuid.New().String(),
			SecOpenID: userId,
			Type:      "broad_start_game",
			Name:      userName,
			Nickname:  userName,
			Level:     level,
			AvatarURL: userHeadImg,
			UserScore: userScore,
			Timestamp: now.UnixMilli(),
		},
	}

	//i.eventManager.AddEventData(liveRoomID, data)
	manager.Get().EventManager().AddEventData(liveRoomID, data)

	i.returnAckMsg(conn, msg)
}

func (i *IndexController) HandleEndGameMessage(conn *websocket.Conn, msg Message) {
	// 从conn获取LiveRoomID和ConnInfo
	//connInfo, found := i.connManager.GetConnInfo(conn)
	connInfo, found := manager.Get().ConnectionManager().GetConnInfo(conn)
	if !found {
		fmt.Println("error: connInfo not found for the given connection")
		return
	}

	liveRoomID := connInfo.ID
	userId := connInfo.UserId

	//i.liveRoomManager.SetLiveRoomStatus(liveRoomID, false)
	//i.scoreManager.FinalizeRoom(liveRoomID)
	manager.Get().LiveRoomManager().SetLiveRoomStatus(liveRoomID, false)
	manager.Get().ScoreManager().FinalizeRoom(liveRoomID)

	// 获取当前时间
	now := time.Now()

	userName := ""
	userHeadImg := ""
	level := 0
	userScore := 0
	//userInfo, err := i.userManager.GetUser(userId)
	userInfo, err := manager.Get().UserManager().GetUser(userId)
	if err == nil {
		userName = userInfo.UserName
		userHeadImg = userInfo.HeadImg
		level = userInfo.Level
		userScore = userInfo.Score
	}

	// 创建一个礼物事件
	data := models.LiveEventData{
		Event: "broad_end_game",
		Data: struct {
			MsgID         string `json:"msg_id"`         // 事件的ID
			SecOpenID     string `json:"sec_openid"`     // 用户的加密openid
			Type          string `json:"type"`           // 事件类型：comment, gift, like
			Content       string `json:"content"`        // 评论内容（仅评论有效）
			Camp          int    `json:"camp"`           // 所属阵营
			Job           int    `json:"job"`            // 所属职业
			SecGiftID     string `json:"sec_gift_id"`    // 加密的礼物id（仅礼物有效）
			GiftNum       int    `json:"gift_num"`       // 送出的礼物数量（仅礼物有效）
			GiftValue     int    `json:"gift_value"`     // 礼物总价值，单位分（仅礼物有效）
			Name          string `json:"name"`           // 用户昵称
			Level         int    `json:"level"`          // 用户等级
			AccGiftScore  int    `json:"acc_gift_score"` // 直播间当前用户累计礼物价值
			LikeNum       string `json:"like_num"`       // 点赞数量（仅点赞有效）
			AvatarURL     string `json:"avatar_url"`     // 用户头像
			Nickname      string `json:"nickname"`       // 用户昵称
			UserScore     int    `json:"user_score"`     // 用户积分
			GiftLevel     int    `json:"gift_level"`     // 礼物等级
			GiftUpgrading int    `json:"gift_upgrading"` // 礼物当前次升级
			GameScore     int    `json:"game_score"`     // 游戏当局分数
			Timestamp     int64  `json:"timestamp"`      // 事件时间戳
		}{
			MsgID:     uuid.New().String(),
			SecOpenID: userId,
			Type:      "broad_end_game",
			Name:      liveRoomID,
			Nickname:  userName,
			Level:     level,
			AvatarURL: userHeadImg,
			UserScore: userScore,
			Timestamp: now.UnixMilli(),
		},
	}

	//i.eventManager.AddEventData(liveRoomID, data)
	manager.Get().EventManager().AddEventData(liveRoomID, data)

	i.returnAckMsg(conn, msg)
}

func (i *IndexController) HandleCloseConnectionMessage(conn *websocket.Conn, msg Message) {
	// 从conn获取LiveRoomID和ConnInfo
	//connInfo, found := i.connManager.GetConnInfo(conn)
	connInfo, found := manager.Get().ConnectionManager().GetConnInfo(conn)
	if !found {
		fmt.Println("error: connInfo not found for the given connection")
		return
	}

	manager.Get().ConnectionManager().Deregister(conn, connInfo.ID)
	conn.Close()
}

func (i *IndexController) HandleGiftMessage(conn *websocket.Conn, msg Message) {
	// 从conn获取LiveRoomID和ConnInfo
	//connInfo, found := i.connManager.GetConnInfo(conn)
	connInfo, found := manager.Get().ConnectionManager().GetConnInfo(conn)
	if !found {
		fmt.Println("error: connInfo not found for the given connection")
		return
	}

	liveRoomID := connInfo.ID
	userId := connInfo.UserId

	msgId := msg.MessageId
	giftId := msg.Data.GiftId

	giftNum := msg.Data.GiftNum

	err := service.LiveRoomService{}.OneUserSendGift(msgId, liveRoomID, userId, giftId, giftNum)
	if err != nil {
		i.returnFailMsg(conn, msg, err.Error())
	}
	fmt.Println(liveRoomID, "号直播间，收货礼物广播事件 已 add")

	i.returnAckMsg(conn, msg)
}

func (i *IndexController) returnAckMsg(conn *websocket.Conn, msg Message) {
	// 构建ack消息
	ackMessage := Message{
		Event:     "ack",
		MessageId: msg.MessageId,
		Data:      InMessageData{},
	}

	// 将ack消息发送给前端
	if err := conn.WriteJSON(ackMessage); err != nil {
		fmt.Println("error sending ack message:", err)
	}
}

func (i *IndexController) returnGenTokenMsg(conn *websocket.Conn, token string, liveRoomId string) {
	// 构建ack消息
	ackMessage := Message{
		Event: "ack_token",
		Data: InMessageData{
			Token:  token,
			RoomId: liveRoomId,
		},
	}

	// 将ack消息发送给前端
	if err := conn.WriteJSON(ackMessage); err != nil {
		fmt.Println("error sending ack message:", err)
	}
}

func (i *IndexController) returnFailMsg(conn *websocket.Conn, msg Message, failMsg string) {

	// 构建ack消息
	ackMessage := Message{
		Event:     "fail",
		MessageId: msg.MessageId,
		Data: InMessageData{
			Content: failMsg,
		},
	}

	// 将ack消息发送给前端
	if err := conn.WriteJSON(ackMessage); err != nil {
		fmt.Println("error sending ack message:", err)
	}
}

func (i *IndexController) GenerateScoreMessage(currentScore int) models.LiveEventData {

	// 获取当前时间
	now := time.Now()

	// 创建一个礼物事件
	data := models.LiveEventData{
		Event: "broad_current_score",
		Data: struct {
			MsgID         string `json:"msg_id"`         // 事件的ID
			SecOpenID     string `json:"sec_openid"`     // 用户的加密openid
			Type          string `json:"type"`           // 事件类型：comment, gift, like
			Content       string `json:"content"`        // 评论内容（仅评论有效）
			Camp          int    `json:"camp"`           // 评论内容（仅评论有效）
			Job           int    `json:"job"`            // 所属职业
			SecGiftID     string `json:"sec_gift_id"`    // 加密的礼物id（仅礼物有效）
			GiftNum       int    `json:"gift_num"`       // 送出的礼物数量（仅礼物有效）
			GiftValue     int    `json:"gift_value"`     // 礼物总价值，单位分（仅礼物有效）
			Name          string `json:"name"`           // 用户昵称
			Level         int    `json:"level"`          // 用户等级
			AccGiftScore  int    `json:"acc_gift_score"` // 直播间当前用户累计礼物价值
			LikeNum       string `json:"like_num"`       // 点赞数量（仅点赞有效）
			AvatarURL     string `json:"avatar_url"`     // 用户头像
			Nickname      string `json:"nickname"`       // 用户昵称
			UserScore     int    `json:"user_score"`     // 用户积分
			GiftLevel     int    `json:"gift_level"`     // 礼物等级
			GiftUpgrading int    `json:"gift_upgrading"` // 礼物当前次升级
			GameScore     int    `json:"game_score"`     // 游戏当局分数
			Timestamp     int64  `json:"timestamp"`      // 事件时间戳
		}{
			MsgID:     uuid.New().String(),
			Type:      "broad_current_score",
			GameScore: currentScore,
			AvatarURL: "http://aegfijaelotgfag/url",
			Nickname:  "this is nick name",
			Timestamp: now.UnixMilli(),
		},
	}

	return data
}

func (i *IndexController) GameStart(ctx *gin.Context) {
	returnStr, _ := utils.WrapJSON("game_start", 0)
	i.broadcast(returnStr, ctx.Query("liveRoomID"))
}

func (i *IndexController) Rank(ctx *gin.Context) {
	returnStr, _ := utils.WrapJSON("rank", 0)
	i.broadcast(returnStr, ctx.Query("liveRoomID"))
}

// controller/indexController.go
func (i *IndexController) Do(conn *websocket.Conn, liveRoomID string) {
	defer func() {
		//i.connManager.Deregister(conn, liveRoomID)
		manager.Get().ConnectionManager().Deregister(conn, liveRoomID)
		conn.Close()
	}()

	for {
		_, message, err := conn.ReadMessage()
		if err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseNormalClosure) {
				fmt.Println("error:", err)
			}
			return
		}

		var msg Message
		if err := json.Unmarshal(message, &msg); err != nil {
			fmt.Println("error unmarshalling message:", err)
			continue
		}

		// 此处是后台生成给自己前端的token
		token := msg.AuthToken
		if token == "" {
			fmt.Printf("error token for send message: %v\n", msg)
			continue
		}

		claim, err := service.AuthService{}.CheckAuth(token)
		if err != nil {
			fmt.Printf("CheckAuth err for token for send message: %v\n", err)
			manager.Get().ConnectionManager().Deregister(conn, liveRoomID)
			conn.Close()
			continue
		}

		connInfo, found := manager.Get().ConnectionManager().GetConnInfo(conn)
		if !found {
			fmt.Println("error: connInfo not found for the given connection")
			manager.Get().ConnectionManager().Deregister(conn, liveRoomID)
			conn.Close()
			return
		}

		if claim.RoomId != connInfo.ID {
			fmt.Println("error: token is wrong")
			manager.Get().ConnectionManager().Deregister(conn, liveRoomID)
			conn.Close()
			return
		}

		switch msg.Event {
		case "send_gift":
			i.HandleGiftMessage(conn, msg)
			break
		case "start_game":
			i.HandleStartGameMessage(conn, msg)
			break
		case "end_game":
			i.HandleEndGameMessage(conn, msg)
			break
		case "close_conn":
			i.HandleCloseConnectionMessage(conn, msg)
			break
		case "ack":
			// 处理ACK消息
			i.handleAck(conn, liveRoomID, msg)
			break
			// 其他事件处理...
		}
	}
}

func (i *IndexController) handleAck(conn *websocket.Conn, liveRoomID string, msg Message) {
	// 解析data获取msg_id
	msgId := msg.MessageId
	// 更新ConnInfo中的ackMsgIds
	manager.Get().ConnectionManager().MarkAck(msgId, conn, liveRoomID)
}
func (i *IndexController) StartTicker() {
	ticker := time.NewTicker(50 * time.Millisecond)
	quit := make(chan struct{})

	// 核心修改点：将整个定时逻辑放入独立goroutine
	go func() {
		defer ticker.Stop()

		for {
			select {
			case <-ticker.C:
				// 阶段1：获取并清空事件数据（原子操作）
				eventsByRoom := manager.Get().EventManager().GetAllAndClear()

				// 阶段2：并发处理每个直播间
				var wg sync.WaitGroup
				for liveRoomID, events := range eventsByRoom {
					if len(events) == 0 {
						continue
					}

					wg.Add(1)
					go func(roomID string, events []models.LiveEventData) {
						defer wg.Done()

						// 子阶段1：序列化数据（无锁环境）
						eventsJSON, err := json.Marshal(events)
						if err != nil {
							fmt.Printf("[%s] JSON marshal error: %v\n", roomID, err)
							return
						}

						// 子阶段2：安全获取连接
						conns := manager.Get().ConnectionManager().Conns()[roomID]

						// 子阶段3：并发发送控制
						var sendWg sync.WaitGroup
						sem := make(chan struct{}, 100) // 控制最大并发
						for conn := range conns {
							sendWg.Add(1)
							sem <- struct{}{}

							go func(c *websocket.Conn) {
								defer func() {
									<-sem
									sendWg.Done()
								}()

								// 写操作自带锁保护
								if err := c.WriteMessage(websocket.TextMessage, eventsJSON); err != nil {
									manager.Get().ConnectionManager().Deregister(c, roomID)
								}
							}(conn)
						}
						sendWg.Wait()
					}(liveRoomID, events)
				}
				wg.Wait()

			case <-quit:
				return
			}
		}
	}()

	// 注册退出清理（根据实际需要调用）
	// defer close(quit)
}

func (i *IndexController) broadcast(data string, liveRoomID string) {
	manager.Get().ConnectionManager().Broadcast(data, liveRoomID)
}

func (i *IndexController) AddEventData(liveRoomID string, eventData models.LiveEventData) {
	//i.eventManager.AddEventData(liveRoomID, eventData)
	manager.Get().EventManager().AddEventData(liveRoomID, eventData)
}

// 添加一个方法来获取当前所有连接
func (i *IndexController) Conns() map[string]map[*websocket.Conn]manager.ConnInfo {
	//return i.connManager.Conns()
	return manager.Get().ConnectionManager().Conns()
}

// 添加互斥锁字段
var mu sync.Mutex

// upGrader 用于升级Get请求到WebSocket协议
var upGrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

// 显式声明实现接口
var _ routes.Registrar = (*IndexController)(nil)
